package com.github.tetrisgame.ui.view;

import android.Manifest;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.github.tetrisgame.R;
import com.github.tetrisgame.databinding.SelectPhotoAppBinding;
import com.github.tetrisgame.utils.AlertDialogUtils;
import com.github.tetrisgame.utils.PermissionUtils;
import com.github.tetrisgame.utils.SkipToPhotoAlbum;
import com.github.tetrisgame.utils.TakePhotoUtils;
import com.github.tetrisgame.utils.UIUtils;

/*
 支持圆形图片
 1. 支持圆形
 2. 设置边框
 3. 设置阴影
 4. 提供默认图片
 5. 从相册或者相机读取图片
 6. 从网络中获取图片
 7. 对图片进行缓存
 8. 点击效果
 */
public class CircularImageView extends View {
    //默认尺寸
    private final int mSize = UIUtils.dp2px(200);
    //外层裁剪的形状
    private final Path mOuterClipPath = new Path();
    //内层图片裁剪的形状
    private final Path mImageCirclePath = new Path();
    //点按效果画笔
    private final Paint mPressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    //阴影画笔
    private final Paint mShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    //边框画笔
    private final Paint mBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    //记录阴影的模糊半径
    private int mShadowRadius = 0;
    //记录阴影的颜色
    private int mShadowColor = Color.parseColor("#77000000");
    //边框尺寸
    private int mBorderWidth = 0;
    //边框颜色
    private int mBorderColor = Color.BLACK;
    //是否需要点按效果
    private boolean mShowPressEffect = false;
    //记录是按下还是抬手
    private boolean isPressed = false;
    //记录显示图片的矩形区域
    private Rect mImageRect;
    private Bitmap mBitmap;


    public CircularImageView(Context context) {
        this(context, null);
    }

    public CircularImageView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CircularImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
        parseAttrs(attrs);
    }

    public void parseAttrs(AttributeSet attrs) {
        TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.CircularImageView);

        mBorderWidth = (int) typedArray.getDimension(R.styleable.CircularImageView_borderWidth, 0);
        mShadowRadius = (int) typedArray.getDimension(R.styleable.CircularImageView_shadowRadius, 0);
        mBorderColor = typedArray.getColor(R.styleable.CircularImageView_borderColor, Color.BLACK);
        mShadowColor = typedArray.getColor(R.styleable.CircularImageView_shadowColor, Color.GRAY);
        mShowPressEffect = typedArray.getBoolean(R.styleable.CircularImageView_ShowPressEffect, false);
        typedArray.recycle();
        mBorderPaint.setColor(mBorderColor);
        mBorderPaint.setStrokeWidth(mBorderWidth);
        if (mShadowRadius > 0) {
            mShadowPaint.setShadowLayer(mShadowRadius, 0, 0, mShadowColor);
        }
    }

    //基础配置
    private void init() {
        //点按效果
        mPressPaint.setStyle(Paint.Style.FILL);
        mPressPaint.setColor(Color.parseColor("#11FFFFFF"));

        //配置边框画笔
        mBorderPaint.setStyle(Paint.Style.STROKE);
    }

    /*
     下面这些set方法就是暴露给外部在代码中设置属性
     */
    public void setBorderWidth(int width) {
        this.mBorderWidth = width;
        mBorderPaint.setStrokeWidth(mBorderWidth);
    }

    public void setBorderColor(int color) {
        this.mBorderColor = color;
        mBorderPaint.setColor(mBorderColor);
    }

    public void setShowPressEffect(boolean show) {
        this.mShowPressEffect = show;
    }

    public void setShadowColor(int color) {
        this.mShadowColor = color;
        mShadowPaint.setColor(mShadowColor);
    }

    public void setShadowRadius(int radius) {
        this.mShadowRadius = radius;
        if (mShadowRadius > 0) {
            mShadowPaint.setShadowLayer(mShadowRadius, 0, 0, Color.parseColor("#72000000"));
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //确定自己想要的尺寸
        int desiredWidth = mSize;
        int desiredHeight = mSize;

        //根据父容器给到的约束获取真实的尺寸
        int realWidth = resolveSizeAndState(desiredWidth, widthMeasureSpec, MEASURED_STATE_TOO_SMALL);
        int realHeight = realWidth;

        //将最终的尺寸设置给视图
        setMeasuredDimension(realWidth, realHeight);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        //配置外层需要裁剪的形状
        mOuterClipPath.addCircle(getWidth() / 2f,
                getHeight() / 2f,
                getWidth() / 2f,
                Path.Direction.CW);
        //配置内层图片需要裁剪的形状
        mImageCirclePath.addCircle(getWidth() / 2f,
                getHeight() / 2f,
                getWidth() / 2f - mShadowRadius - mBorderWidth,
                Path.Direction.CW);
        //确定图片的矩形区域
        mImageRect = new Rect(
                mShadowRadius + mBorderWidth,
                mShadowRadius + mBorderWidth,
                getWidth() - mShadowRadius - mBorderWidth,
                getHeight() - mShadowRadius - mBorderWidth
        );
    }

    private Bitmap getBitmap() {
        if (mBitmap == null) {
            mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bg_image);
        }
        return mBitmap;
    }

    @Override
    protected void onDraw(@NonNull Canvas canvas) {
        super.onDraw(canvas);
        //将外层的canvas裁剪为圆形
        //如果是常规的矩形 clipRect 其他形状使用clipPath
        //首先得确定好裁剪的路径Path
        canvas.clipPath(mOuterClipPath);

        //绘制阴影
        if (mShadowRadius > 0) {
            canvas.drawCircle(getWidth() / 2f,
                    getHeight() / 2f,
                    getWidth() / 2f - mShadowRadius,
                    mShadowPaint);
        }

        //绘制边框
        if (mBorderWidth > 0) {
            canvas.drawCircle(getWidth() / 2f,
                    getHeight() / 2f,
                    getWidth() / 2f - mShadowRadius - mBorderWidth / 2f,
                    mBorderPaint);
        }

        //裁剪显示圆形图片的图层
        canvas.save();
        canvas.clipPath(mImageCirclePath);
        canvas.drawBitmap(getBitmap(), null, mImageRect, null);
        canvas.restore();

        //绘制点按效果
        if (mShowPressEffect && isPressed) {
            canvas.drawCircle(getWidth() / 2f, getHeight() / 2f, getWidth() / 2f - mShadowRadius - mBorderWidth, mPressPaint);
        }


    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!mShowPressEffect) return true;

        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            isPressed = true;
            invalidate();
        }
        if (event.getAction() == MotionEvent.ACTION_UP) {
            isPressed = false;
            invalidate();
            if (PermissionUtils.sharedInstance.checkPermission(Manifest.permission.CAMERA)) {
                showDialog();
            } else {
                PermissionUtils.sharedInstance.requestPermission(Manifest.permission.CAMERA, granted -> {
                    if (granted) {
                        showDialog();
                    }
                });
            }
        }
        return true;
    }


    public void showDialog() {
        LayoutInflater inflater = LayoutInflater.from(getContext());
        SelectPhotoAppBinding binding = SelectPhotoAppBinding.inflate(inflater);
        AlertDialogUtils<SelectPhotoAppBinding> dialogUtils = new AlertDialogUtils<SelectPhotoAppBinding>(binding) {
            @Override
            public void initEvent(SelectPhotoAppBinding binding) {
                super.initEvent(binding);
                binding.takePhoto.setOnClickListener(v -> {
                    TakePhotoUtils.sharedInstance.openCamera(uri -> {
                        Bitmap selectedBitmap = BitmapFactory.decodeStream(
                                getContext().getContentResolver().openInputStream(uri));
                        setImageBitmap(selectedBitmap);
                    });
                    dismiss();
                });
                binding.photoAlbum.setOnClickListener(v -> {
                    SkipToPhotoAlbum.sharedInstance.openPhotoAlbum(selectedPhotoUri -> {
                        Bitmap selectedBitmap = BitmapFactory.decodeStream(
                                getContext().getContentResolver().openInputStream(selectedPhotoUri));
                        setImageBitmap(selectedBitmap);
                    });
                    dismiss();
                });
            }
        };
        dialogUtils.show();
    }

    //绘制三角形
    private void drawTriangle() {
        mOuterClipPath.moveTo(getWidth() / 2f, 0);
        mOuterClipPath.lineTo(0, getHeight());
        mOuterClipPath.lineTo(getWidth(), getHeight());
        mOuterClipPath.close();
    }

    //绘制圆形
    private void drawCircle() {
        mOuterClipPath.moveTo(getWidth() / 2f, 0);
        mOuterClipPath.lineTo(getWidth() / 2f, getHeight() / 2f);
        mOuterClipPath.addCircle(getWidth() / 2f, getHeight() * 3 / 4f, getHeight() / 4f, Path.Direction.CW);
        mOuterClipPath.lineTo(getWidth(), 0);
    }

    private void drawBezel() {
        mOuterClipPath.moveTo(0, getHeight() / 2f);
        mOuterClipPath.cubicTo(
                getWidth() / 4f,
                0,
                getWidth() * 3 / 4f,
                getHeight(),
                getWidth(),
                getHeight() / 2f);
        mOuterClipPath.close();
    }

    private void drawArc() {
        mOuterClipPath.addArc(
                UIUtils.dp2pxF(2),
                UIUtils.dp2pxF(2),
                getWidth() - UIUtils.dp2pxF(2),
                getHeight() - UIUtils.dp2pxF(2), 0f, 360
        );
    }

    public void setImageBitmap(Bitmap bitmap) {
        this.mBitmap = bitmap;
        invalidate();
    }

    private void drawImage(Canvas canvas) {
        //添加一张图片
        canvas.save();
        //对canvas做额外操作 裁剪 旋转 移动
        canvas.clipPath(mImageCirclePath);
        Rect rect = new Rect(
                UIUtils.dp2px(20),
                UIUtils.dp2px(20),
                getWidth() - UIUtils.dp2px(20),
                getHeight() - UIUtils.dp2px(20)
        );
        canvas.drawBitmap(getBitmap(), null, rect, null);
        //恢复
        canvas.restore();
    }
}













